﻿using System;
using System.Linq;
using OSCSchema;
using OutlookSocialProvider;

namespace OSC.Base
{
    public class CachedSession : ISocialSession, ISocialSession2
    {
        #region Fields
        private readonly IConverter<IPerson, personType> m_PersonConverter;
        private readonly IConverter<Activity, activityDetailsType> m_ActivityConverter;
        private readonly IConverter<IActivityTemplate, activityTemplateContainerType> m_ActivityTemplateConverter;
        private readonly ICachingStrategy m_CachingStrategy;
        private readonly IOSCSerializer m_Serializer = new OSCSerializer();
        private readonly ISocialConnector m_Session;
        private IPerson m_LoggedOnUser;
        #endregion

        #region Properties
        public string SiteUrl { private get; set; }
        public string LoggedOnUserID
        {
            get { return m_LoggedOnUser.UserId; }
        }
        public string LoggedOnUserName
        {
            get { return m_LoggedOnUser.FullName; }
        }
        #endregion

        #region Constructor
        public CachedSession(ISocialConnector session, ICachingStrategy cachingStrategy)
            : this(session, cachingStrategy, new PersonConverter(), new ActivityConverter(), new ActivityTemplateConverter())
        { }
        public CachedSession(ISocialConnector session,
                             ICachingStrategy cachingStrategy,
                             IConverter<IPerson, personType> personConverter,
                             IConverter<Activity, activityDetailsType> activityConverter,
                             IConverter<IActivityTemplate, activityTemplateContainerType> activityTemplateConverter)
        {
            m_CachingStrategy = cachingStrategy;
            m_ActivityTemplateConverter = activityTemplateConverter;
            m_ActivityConverter = activityConverter;
            m_PersonConverter = personConverter;
            m_Session = session;
            SiteUrl = session.SiteUrl;
        }
        #endregion

        #region Methods
        public void Logon(string userName, string password)
        {
            //m_LoggedOnUser = m_CachingStrategy.Logon(userName, password);
        }
        public void LogonWeb(string connectIn, out string connectOut)
        {
            m_LoggedOnUser = m_CachingStrategy.Logon("", "", out connectOut);
        }
        public string GetLogonUrl()
        {
            return m_Session.LogonUrl;
        }
        public string GetNetworkIdentifier()
        {
            return m_Session.LogonUrl;
        }
        public ISocialProfile GetLoggedOnUser()
        {
            return new SocialProfile(m_LoggedOnUser, m_Session, m_CachingStrategy, m_PersonConverter, m_ActivityConverter, m_ActivityTemplateConverter);
        }
        public ISocialPerson GetPerson(string userID)
        {
            var person = m_CachingStrategy.GetPerson(userID);
            return new SocialPerson(person, m_Session, m_CachingStrategy, m_PersonConverter, m_ActivityConverter, m_ActivityTemplateConverter);
        }
        public string FindPerson(string userID)
        {
            var persons = m_CachingStrategy.FindPerson(userID);
            var friends = new friends
                                  {
                                      person = persons.Select(m_PersonConverter.Convert).ToArray()
                                  };
            return m_Serializer.Serialize(friends);
        }
        public string GetActivities(string[] emailAddresses, DateTime startTime)
        {
            //This is not needed because we are using GetActivitiesEx
            throw new NotImplementedException();
        }
        public void FollowPerson(string emailAddress)
        {
            //If the provider implements the ISocialSession2 interface and has set followPerson as true in the capabilities XML, the OSC calls FollowPersonEx instead 
            throw new NotImplementedException();
        }
        public void UnFollowPerson(string userID)
        {
            m_Session.Unfollow(userID);
        }
        public string GetPeopleDetails(string personsAddresses)
        {
            var hashedAddresses = m_Serializer.DeserializeHashedAddresses(personsAddresses);
            if (hashedAddresses == null) return string.Empty;
            var persons = hashedAddresses.personAddresses.Select(m => m_CachingStrategy.GetUserId(m.hashedAddress))
                                                         .Where(m => !string.IsNullOrEmpty(m))
                                                         .Select(id => m_CachingStrategy.GetPerson(id))
                                                         .Select(m_PersonConverter.Convert)
                                                         .ToArray();
            var friends = new friends { person = persons };
            return m_Serializer.Serialize(friends);
        }
        public string GetActivitiesEx(string[] hashedAddresses, DateTime startTime)
        {
            var userId = m_CachingStrategy.GetUserId(hashedAddresses);
            if (string.IsNullOrEmpty(userId)) return null;
            var person = new SocialPerson(m_CachingStrategy.GetPerson(userId), m_Session, m_CachingStrategy, m_PersonConverter, m_ActivityConverter, m_ActivityTemplateConverter);

            return person.GetActivities(startTime);
        }
        public void FollowPersonEx(string[] emailAddresses, string displayName)
        {
            m_Session.Follow(emailAddresses, displayName);
        }
        public void LogonCached(string connectIn, string userName, string password, out string connectOut)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
